package com.tbit.uqbike.client.controller;

import com.alibaba.fastjson.JSONObject;
import com.tbit.uqbike.client.constant.annotation.PreventDuplication;
import com.tbit.uqbike.client.exception.BaseException;
import com.tbit.uqbike.client.pojo.InvoiceRecord;
import com.tbit.uqbike.client.pojo.Result;
import com.tbit.uqbike.client.pojo.User;
import com.tbit.uqbike.client.pojo.dto.AddInvoiceRecordDTO;
import com.tbit.uqbike.client.pojo.dto.ReOpenDTO;
import com.tbit.uqbike.client.pojo.dto.ReOpenEditInvoiceRecordDTO;
import com.tbit.uqbike.client.pojo.dto.ReOpenInvoiceRecordDTO;
import com.tbit.uqbike.client.pojo.vo.InvoiceCardLogVO;
import com.tbit.uqbike.client.pojo.vo.InvoiceRideLogVO;
import com.tbit.uqbike.client.service.AutoInvoiceService;
import com.tbit.uqbike.client.service.InvoiceRecordService;
import com.tbit.uqbike.client.service.TokenService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotNull;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 发票
 *
 * @Author:BUGTian
 * @DATE: 2023/8/29
 */
@Slf4j
@RestController
@RequestMapping("/invoiceRecord")
public class InvoiceRecordController {

    @Autowired
    private InvoiceRecordService invoiceRecordService;
    @Autowired
    private AutoInvoiceService autoInvoiceService;
    @Autowired
    private TokenService tokenService;


    /**
     * 查询开票信息（骑行订单）
     *
     * @param token     用户token
     * @param startTime 起始时间
     * @param endTime   终止时间
     * @param minMoney  最低价(单位：分)
     * @param maxMoney  最高价(单位：分)
     * @return
     */
    @GetMapping("/queryInvoiceRideLog")
    public Result<List<InvoiceRideLogVO>> queryInvoiceRideLog(@NotNull String token, Date startTime, Date endTime, Long minMoney, Long maxMoney) {
        return invoiceRecordService.queryInvoiceRideLog(token, startTime, endTime, minMoney, maxMoney);
    }

    /**
     * 查询开票信息（套餐订单）
     *
     * @param token        用户token
     * @param startTime    起始时间
     * @param endTime      终止时间
     * @param minMoney     最低价(单位：分)
     * @param maxMoney     最高价(单位：分)
     * @param rechargeType 订单类型（1:免押卡 2:骑行卡 4:会员卡 5:优惠券套餐）
     * @return
     */
    @GetMapping("/queryInvoiceCardLog")
    public Result<List<InvoiceCardLogVO>> queryInvoiceCardLog(@NotNull String token, Date startTime, Date endTime, Long minMoney, Long maxMoney, Integer rechargeType) {
        return invoiceRecordService.queryInvoiceCardLog(token, startTime, endTime, minMoney, maxMoney, rechargeType);
    }

    /**
     * 开票
     *
     * @param token               用户token
     * @param addInvoiceRecordDTO 开票传输对象
     * @return
     */
    @PreventDuplication(expireSeconds = 5)
    @PostMapping("/add")
    public Result addInvoiceRecord(@NotNull String token, @RequestBody AddInvoiceRecordDTO addInvoiceRecordDTO) {
        return invoiceRecordService.addInvoiceRecord(token, addInvoiceRecordDTO);
    }

    /**
     * 查询开票历史
     *
     * @param token 用户token
     * @return
     */
    @GetMapping("/queryInvoiceRecord")
    public Result<List<InvoiceRecord>> queryInvoiceRecord(@NotNull String token) {
        return invoiceRecordService.queryInvoiceRecord(token);
    }

    /**
     * 根据发票历史id查询骑行订单详情
     *
     * @param token 用户token
     * @param id    发票历史id
     * @return
     */
    @GetMapping("/getRideLogById")
    public Result<List<InvoiceRideLogVO>> getRideLogById(@NotNull String token, @NotNull Integer id) {
        return invoiceRecordService.getRideLogById(token, id);
    }

    /**
     * 根据发票历史id查询套餐订单详情
     *
     * @param token 用户token
     * @param id    发票历史id
     * @return
     */
    @GetMapping("/getCardLogById")
    public Result<List<InvoiceCardLogVO>> getCardLogById(@NotNull String token, @NotNull Integer id) {
        return invoiceRecordService.getCardLogById(token, id);
    }

    /**
     * 查询可申请重开订单（重新选择订单）
     *
     * @param token        用户token
     * @param id           发票历史id
     * @param orderType    订单类型(1:骑行订单 2:套餐订单)
     * @param startTime    起始时间
     * @param endTime      终止时间
     * @param minMoney     最低价(单位：分)
     * @param maxMoney     最高价(单位：分)
     * @param rechargeType 订单类型（1:免押卡 2:骑行卡 4:会员卡 5:优惠券套餐）
     * @return
     */
    @GetMapping("/canReopen")
    public Result<Object> canReopenInvoiceRecord(@NotNull String token, @NotNull Integer id, @NotNull Integer orderType, Date startTime, Date endTime, Long minMoney, Long maxMoney, Integer rechargeType) {
        return invoiceRecordService.canReopenInvoiceRecord(token, id, orderType, startTime, endTime, minMoney, maxMoney, rechargeType);
    }

    /**
     * 重开发票（重新选择订单），接口已废弃
     *
     * @param token                  用户token
     * @param reOpenInvoiceRecordDTO
     * @return
     */
    @PutMapping("/reOpen")
    public Result reOpenInvoiceRecord(@NotNull String token, @RequestBody ReOpenInvoiceRecordDTO reOpenInvoiceRecordDTO) {
        return invoiceRecordService.reOpenInvoiceRecord(token, reOpenInvoiceRecordDTO);
    }

    /**
     * 重开发票（修改发票信息），接口已废弃
     *
     * @param token
     * @param reOpenEditInvoiceRecordDTO
     * @return
     */
    @PutMapping("/reOpenEdit")
    public Result reOpenEditInvoiceRecord(@NotNull String token, @RequestBody ReOpenEditInvoiceRecordDTO reOpenEditInvoiceRecordDTO) {
        return invoiceRecordService.reOpenEditInvoiceRecord(token, reOpenEditInvoiceRecordDTO);
    }

    /**
     * 重开发票
     *
     * @param token     用户token
     * @param reOpenDTO
     * @return
     */
    @PutMapping("/reOpenNew")
    public Result reOpenInvoiceRecordNew(@NotNull String token, @RequestBody ReOpenDTO reOpenDTO) {
        return invoiceRecordService.reOpenInvoiceRecordNew(token, reOpenDTO);
    }

    /**
     * 申请重发
     *
     * @param token 用户token
     * @param email 邮箱地址
     * @param id    发票历史id
     * @return
     */
    @GetMapping("/reSend")
    public Result reSend(@NotNull String token, @NotNull String email, @NotNull Integer id) {
        return invoiceRecordService.reSend(token, email, id);
    }

    /**
     * 修改邮箱
     *
     * @param token 用户token
     * @param email 邮箱地址
     * @param id    发票历史id
     * @return
     */
    @PutMapping("/editEmail")
    public Result editEmail(@NotNull String token, @NotNull String email, @NotNull Integer id) {
        return invoiceRecordService.editEmail(token, email, id);
    }

    /**
     * @description: 自动重新生成发票
     * @author: mo.shanyong
     * @date: 2025/4/7 13:45
     * @param: invoiceId 发票Id
     * @return: com.tbit.uqbike.client.pojo.Result<java.lang.Object>
     */
    @RequestMapping("/reAutoInvoicing")
    public Result<Object> reAutoInvoicing(Integer invoiceId){
        autoInvoiceService.reAutoInvoicing(invoiceId);
        return Result.success();
    }

    /**
     * @description: 联想企业抬头信息
     * @author: mo.shanyong
     * @date: 2025/4/3 19:34
     * @param: company 公司名称
     * @return: com.tbit.uqbike.client.pojo.Result<com.alibaba.fastjson.JSONObject>
     */
    @GetMapping("/associateCompany")
    public Result<List<JSONObject>> associateCompany(String company,String token){
        User user = tokenService.getUser(token);
        if (Objects.isNull(user)){
            throw new BaseException("用户登录过期，请重新登录");
        }
        List<JSONObject> jsonObjectList = autoInvoiceService.associateCompany(company, user.getAccountId());
        return Result.success(jsonObjectList);
    }
    /**
     * @description: 开票异步回调
     * @author: mo.shanyong
     * @date: 2025/4/3 19:41
     * @param: request
     * @return: com.tbit.uqbike.client.pojo.Result<java.lang.Object>
     */
    @RequestMapping("/invoiceNotify")
    public void invoiceNotify(HttpServletRequest request) throws Exception {
        log.info("开票回调--------/invoiceRecord/invoiceNotify");
        String notifyBody = this.readRequestBody(request);
        log.info("开票异步回调响应体" + notifyBody);
        autoInvoiceService.invoiceNotify(notifyBody);
    }

    private String readRequestBody(HttpServletRequest request) throws Exception {
        ServletInputStream inputStream = request.getInputStream();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len;
        while ((len = inputStream.read(buffer)) != -1) {
            baos.write(buffer, 0, len);
        }
        return baos.toString(StandardCharsets.UTF_8.name());
    }


}
